﻿#include <iostream>
#include <iomanip>
#include <cmath>
#include <string>
#include <cctype>
#include <functional>  // 新增functional头文件

using namespace std;

class HeatTransfer {
private:
    const static int MAX_GRID_SIZE = 100;  // 最大网格尺寸
    double grid[MAX_GRID_SIZE][MAX_GRID_SIZE];  // 温度网格
    int rows, cols;  // 网格行数和列数
    const double tolerance = 1e-6;  // 收敛阈值

    // 检查输入是否为正整数（私有辅助函数）
    bool isPosInt(const string& input) {
        if (input.empty()) return false;
        for (char c : input) {
            if (!isdigit(c)) return false;
        }
        return true;
    }

    // 检查输入是否为合法浮点数（私有辅助函数）
    bool isDouble(const string& input) {
        bool pointSeen = false, hasDigit = false;
        for (size_t i = 0; i < input.size(); ++i) {
            char c = input[i];
            if (i == 0 && c == '-') continue;  // 允许负号开头
            if (c == '.') {
                if (pointSeen) return false;
                pointSeen = true;
            }
            else if (isdigit(c)) {
                hasDigit = true;
            }
            else {
                return false;
            }
        }
        return hasDigit;
    }

    // 通用输入函数（使用std::function接受Lambda）
    template <typename T>
    T getInput(const string& prompt, function<bool(const string&)> validator) {
        string input;
        T value;
        while (true) {
            cout << prompt;
            getline(cin, input);
            if (validator(input)) {
                // 根据类型选择转换函数（兼容C++11）
                if (is_same<T, int>::value) {  // 替换is_same_v为模板特化
                    value = stoi(input);
                }
                else {
                    value = stod(input);
                }
                return value;
            }
            cout << "输入不合法，请重新输入\n";
        }
    }

public:
    // 构造函数：初始化网格尺寸和初始温度
    HeatTransfer() {
        // 网格尺寸验证（包含范围检查）
        rows = getInput<int>("请输入网格行数（1-100的正整数）: ", [this](const string& s) {
            return isPosInt(s) && stoi(s) >= 1 && stoi(s) <= MAX_GRID_SIZE;
            });

        cols = getInput<int>("请输入网格列数（1-100的正整数）: ", [this](const string& s) {
            return isPosInt(s) && stoi(s) >= 1 && stoi(s) <= MAX_GRID_SIZE;
            });

        double initialTemp = getInput<double>("请输入初始温度（合法浮点数）: ",
            [this](const string& s) { return isDouble(s); });

        // 初始化网格
        for (int i = 0; i < rows; ++i) {
            for (int j = 0; j < cols; ++j) {
                grid[i][j] = initialTemp;
            }
        }
    }

    // 设置边界温度（封装输入和边界条件设置）
    void setBoundaryTemperatures() {
        double tTemp = getInput<double>("请输入上边界温度（合法浮点数）: ",
            [this](const string& s) { return isDouble(s); });
        double bTemp = getInput<double>("请输入下边界温度（合法浮点数）: ",
            [this](const string& s) { return isDouble(s); });
        double lTemp = getInput<double>("请输入左边界温度（合法浮点数）: ",
            [this](const string& s) { return isDouble(s); });
        double rTemp = getInput<double>("请输入右边界温度（合法浮点数）: ",
            [this](const string& s) { return isDouble(s); });

        // 应用边界条件（明确边界索引范围）
        for (int i = 0; i < rows; ++i) {
            grid[i][0] = lTemp;           // 左边界（第0列）
            grid[i][cols - 1] = rTemp;    // 右边界（最后一列）
        }
        for (int j = 0; j < cols; ++j) {
            grid[0][j] = tTemp;           // 上边界（第0行）
            grid[rows - 1][j] = bTemp;    // 下边界（最后一行）
        }
    }

    // 更新温度分布（核心计算逻辑，明确跳过边界节点）
    void updateGrid() {
        double newGrid[MAX_GRID_SIZE][MAX_GRID_SIZE];
        // 仅更新内部节点（非边界节点）
        for (int i = 1; i < rows - 1; ++i) {  // 行范围：1到rows-2（含）
            for (int j = 1; j < cols - 1; ++j) {  // 列范围：1到cols-2（含）
                newGrid[i][j] = (grid[i - 1][j] + grid[i + 1][j] +
                    grid[i][j - 1] + grid[i][j + 1]) / 4.0;
            }
        }
        // 复制回原网格，边界节点保持不变
        for (int i = 0; i < rows; ++i) {
            for (int j = 0; j < cols; ++j) {
                if (i == 0 || i == rows - 1 || j == 0 || j == cols - 1) {
                    // 边界节点不更新，保留原值
                }
                else {
                    grid[i][j] = newGrid[i][j];
                }
            }
        }
    }

    // 计算温度分布直到收敛（包含迭代控制和输出）
    void computeDistribution() {
        int iteration = 1;
        double maxDiff;

        do {
            maxDiff = 0.0;
            double prevGrid[MAX_GRID_SIZE][MAX_GRID_SIZE];

            // 保存当前状态（包括边界节点）
            for (int i = 0; i < rows; ++i) {
                for (int j = 0; j < cols; ++j) {
                    prevGrid[i][j] = grid[i][j];
                }
            }

            // 执行更新
            updateGrid();

            // 计算最大差异（仅内部节点，边界节点差异恒为0）
            for (int i = 1; i < rows - 1; ++i) {
                for (int j = 1; j < cols - 1; ++j) {
                    double diff = fabs(grid[i][j] - prevGrid[i][j]);
                    if (diff > maxDiff) maxDiff = diff;
                }
            }

            // 输出当前迭代结果（优化输出格式，增加表格标题）
            cout << "\n--------------------------- 迭代 " << iteration << " ---------------------------\n";
            cout << "最大差异: " << scientific << setprecision(6) << maxDiff
                << "  (阈值: " << scientific << tolerance << ")\n";
            cout << setw(6) << "行\\列" << "|";
            for (int j = 0; j < cols; ++j) {
                cout << setw(8) << j;
            }
            cout << "\n" << string(7 + cols * 8, '-') << endl;
            for (int i = 0; i < rows; ++i) {
                cout << setw(4) << i << " |";
                for (int j = 0; j < cols; ++j) {
                    cout << fixed << setw(8) << setprecision(2) << grid[i][j];
                }
                cout << endl;
            }

            iteration++;
        } while (maxDiff > tolerance);

        cout << "\n计算完成！共进行 " << iteration - 1 << " 次迭代\n"
            << "最终温度分布（保留2位小数）:\n";
        // 输出最终结果（简化格式）
        for (int i = 0; i < rows; ++i) {
            for (int j = 0; j < cols; ++j) {
                cout << fixed << setw(8) << setprecision(2) << grid[i][j];
            }
            cout << endl;
        }
    }
};

int main() {
    cout << "=== 二维稳态热传导问题求解 ===" << endl;
    HeatTransfer solver;
    solver.setBoundaryTemperatures();
    solver.computeDistribution();
    return 0;
}
